package com.fhsk.file.common.utils;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import java.io.IOException;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * 罗纳德·李维斯特（Ron [R]ivest）、阿迪·萨莫尔（Adi [S]hamir）和伦纳德·阿德曼（Leonard [A]dleman）
 * 由于非对称加密速度极其缓慢，一般文件不使用它来加密而是使用对称加密，
 * 非对称加密算法可以用来对对称加密的密钥加密，这样保证密钥的安全也就保证了数据的安全
 *
 * @author IceWee
 * @version 1.0
 * @date 2012-4-26
 */
public class RSAUtil {
    //生成秘钥对
    public static KeyPair getKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return keyPair;
    }

    //获取公钥(Base64编码)
    public static String getPublicKey(KeyPair keyPair) {
        PublicKey publicKey = keyPair.getPublic();
        byte[] bytes = publicKey.getEncoded();
        return byte2Base64(bytes).replaceAll("\r", "").replaceAll("\n", "");
    }

    //获取私钥(Base64编码)
    public static String getPrivateKey(KeyPair keyPair) {
        PrivateKey privateKey = keyPair.getPrivate();
        byte[] bytes = privateKey.getEncoded();
        return byte2Base64(bytes).replaceAll("\r", "").replaceAll("\n", "");
    }

    //将Base64编码后的公钥转换成PublicKey对象
    public static PublicKey string2PublicKey(String pubStr) throws Exception {
        byte[] keyBytes = base642Byte(pubStr);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }

    //将Base64编码后的私钥转换成PrivateKey对象
    public static PrivateKey string2PrivateKey(String priStr) throws Exception {
        byte[] keyBytes = base642Byte(priStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }

    //公钥加密
    public static String publicEncrypt(String content, String publicKeyStr) throws Exception {
        PublicKey publicKey = RSAUtil.string2PublicKey(publicKeyStr);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] bytes1 = content.getBytes();
        byte[] bytes = cipher.doFinal(bytes1);
        String byte2Base64 = RSAUtil.byte2Base64(bytes);
        return byte2Base64;
    }

    //私钥解密
    public static String privateDecrypt(String contentStr, String privateKeyStr) throws Exception {
        PrivateKey privateKey = RSAUtil.string2PrivateKey(privateKeyStr);
        byte[] content = RSAUtil.base642Byte(contentStr);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] bytes = cipher.doFinal(content);
        return new String(bytes);
    }

    //字节数组转Base64编码
    public static String byte2Base64(byte[] bytes) {
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(bytes);
    }

    //Base64编码转字节数组
    public static byte[] base642Byte(String base64Key) throws IOException {
        BASE64Decoder decoder = new BASE64Decoder();
        return decoder.decodeBuffer(base64Key);
    }

    public static void main(String[] args) {
        try {
//            //===============生成公钥和私钥，公钥传给客户端，私钥服务端保留==================
//            //生成RSA公钥和私钥，并Base64编码
//            KeyPair keyPair = RSAUtil.getKeyPair();
//            String publicKeyStr = RSAUtil.getPublicKey(keyPair);
//            String privateKeyStr = RSAUtil.getPrivateKey(keyPair);
//            System.out.println("RSA公钥Base64编码:" + publicKeyStr);
//            System.out.println("RSA私钥Base64编码:" + privateKeyStr);
//
//            //=================客户端=================
//            //hello, i am infi, good night!加密
//            String message = "hello, i am infi, good night!";
//            //用公钥加密
//            String contentStr = RSAUtil.publicEncrypt(message, publicKeyStr);
//            System.out.println("公钥加密并Base64编码的结果：" + contentStr);
//
//
//            //===================服务端================

            String publicKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKlZcLtzDcghjdvkxOvv/iZkx6aIScsc/GgTpJdF7c5khHWWf0LxcBnzmYJdXa5Iu7W6lUtNvopUHwEqBehydW3aDwLrPGopJipRmrqC/f6xOYz3lyR4OXBWVUuQ+O1l1eOiHdv2euSg6Jb+au9M5aPZNsrlGS27mVGGCvyuLBLQIDAQAB";

            String s = RSAUtil.publicEncrypt("17b2b0173e8ba74a6b4389b31839c3c719b30482", publicKeyStr);

            System.out.println(s);

//            String privateDecrypt = RSAUtil.privateDecrypt("", privateKeyStr);
//            //解密后的明文
//            System.out.println("解密后的明文: " + privateDecrypt);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
